<?php
// 应用公共文件

if (!function_exists('web_config')) {

    /**
     * 查询网站配置
     * @param string $key 键
     * @param mixed $default 默认值
     * @return mixed
     */
    function web_config($itemsId = 0, $key = null, $default = null)
    {
        return app()->make(\app\common\repositories\system\SystemConfigRepository::class)->getConfig($itemsId, $key, $default);
    }
}


if (!function_exists('get_file_mime_type')) {
    /**
     * 生成uuid
     *
     * @return string
     */
    function get_file_mime_type(string $filePath)
    {
        if (file_exists($filePath)) {
            $mimeTypesServer = new \Symfony\Component\Mime\MimeTypes();
            $ext = pathinfo($filePath, PATHINFO_EXTENSION);
            $mimeTypes = $mimeTypesServer->getMimeTypes($ext);
            if ($mimeTypes) {
                return $mimeTypes[0];
            }
            return $mimeTypesServer->guessMimeType($filePath);
        }
        return '';
    }
}

if (!function_exists('sms_verify')) {
    /**
     * 短信验证码验证
     * @param int $itemsId
     * @param string $mobile
     * @param string $smsCode
     * @param int $smsType
     * @return void
     * @throws \api\sms\exception\SmsException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     *
     * @author Amos
     * 2024-01-24 21:53
     */
    function sms_verify(int $itemsId, string $mobile, string $smsCode, int $smsType)
    {
        \app\common\services\SmsService::init($itemsId)->checkVerifyCode($mobile, $smsCode, $smsType);
    }
}

if (!function_exists('get_weeks')) {
    /**
     * 获取最近七天所有日期
     */
    function get_weeks($time = '', $format = 'Y-m-d')
    {
        $time = $time != '' ? $time : time();
        //组合数据
        $date = [];
        for ($i = 1; $i <= 7; $i++) {
            $date[$i] = date($format, strtotime('+' . $i - 7 . ' days', $time));
        }
        return $date;
    }
}

if (!function_exists('get_month')) {
    /**
     * 获取近12个月
     */
    function get_month()
    {//获取日期
        $now_year = date('Y');
        $now_month = date('m');
        $date1 = $date2 = array();
        for ($i = 1; $i <= $now_month; $i++) {
            if ($i < 10) {
                $i = '0' . $i;
            }
            $date1[] = $now_year . "-" . $i;
        }

        for ($i = (count($date1) + 1); $i <= 12; $i++) {
            if ($i < 10) {
                $i = '0' . $i;
            }
            $date2[] = ($now_year - 1) . "-" . $i;
        }
        $date = array_merge($date2, $date1);

        return $date;
    }
}


if (!function_exists('property_auth')) {
    /**
     * 后台权限检测
     * @param string $url 地址
     * @return bool
     */
    function property_auth($url)
    {
        return app()->make(\app\common\repositories\property\users\PropertyUsersRepository::class)->checkAuth($url);
    }
}

if (!function_exists('entire_auth')) {
    /**
     * 后台权限检测
     * @param string $url 地址
     * @return bool
     */
    function entire_auth($url)
    {
        return app()->make(\app\common\repositories\entire\users\EntireUsersRepository::class)->checkAuth($url);
    }
}

if (!function_exists('exception_log')) {
    /**
     * 异常日志写入
     *
     * @param string $msg 错误信息
     * @param Throwable $e 异常类
     * @param bool $isDetail 是否记录详细信息
     */
    function exception_log($msg, $e, $isDetail = true)
    {
        if ($isDetail) {
            \app\helper\Log::exceptionWrite($msg, $e);
        } else {
            \think\facade\Log::write($msg . ', error_msg:' . $e->getMessage(), 'error');
        }
    }
}

if (!function_exists('arr_specify_get')) {
    /**
     * 数组指定获取
     *
     * @param array $arr 数组
     * @param array|string $keys 要获取的键名
     * @param bool $multilevel 是否是多级数组
     * @return array
     */
    function arr_specify_get($arr, $keys, $multilevel = false)
    {
        if (!is_array($keys)) {
            $keys = explode(',', $keys);
        }
        if ($multilevel) {
            $tempData = [];
            foreach ($arr as $k => $v) {
                if (is_array($v) && !empty($v)) {
                    $arr = arr_specify_get($v, $keys, true);
                    $tempData[$k] = $arr;
                } else {
                    if (in_array($k, $keys)) {
                        $tempData[$k] = $v;
                    }
                }
            }
            return $tempData;
        } else {
            $tempData = [];
            foreach ($arr as $k => $v) {
                if (in_array($k, $keys)) {
                    $tempData[$k] = $v;
                }
            }

            return $tempData;
        }
    }
}
if (!file_exists('arr_level_sort')) {
    /**
     * 数组按层级排序
     * @param array $array 数组
     * @param int $type 1一级 2多级
     * @param int $fid 上级id
     * @param int $level 层数·
     * @return array
     */
    function arr_level_sort($array, $type = 1, $fid = 0, $level = 0)
    {
        $column = [];
        if ($type == 2) {
            foreach ($array as $key => $vo) {
                if ($vo['pid'] == $fid) {
                    $vo['level'] = $level;
                    $column[$key] = $vo;
                    $column [$key][$vo['id']] = arr_level_sort($array, $type, $vo['id'], $level + 1);
                }
            }
        } else {
            foreach ($array as $key => $vo) {
                if ($vo['pid'] == $fid) {
                    $vo['level'] = $level;
                    $column[] = $vo;
                    $column = array_merge($column, arr_level_sort($array, $type, $vo['id'], $level + 1));
                }
            }
        }

        return $column;
    }
}


if (!function_exists('get_arr_column')) {

    /**
     * 获取数组中的某一列
     *
     * @param array $arr 数组
     * @param string $keyName 列名
     * @return array 返回那一列的数组
     */
    function get_arr_column($arr, $keyName)
    {
        $returnArr = array();
        if (!empty($arr)) {
            foreach ($arr as $k => $v) {
                $returnArr[] = $v[$keyName];
            }
        }
        return $returnArr;
    }

}

if (!function_exists('convert_arr_key')) {

    /**
     * 将数组中的某个键值作为键
     *
     * @param array $arr 数组
     * @param string $keyName 键名
     * @param bool $multilevel 是否保留多级
     * @return array
     */
    function convert_arr_key($arr, $keyName, $multilevel = false)
    {
        $arr2 = array();
        if ($multilevel) {
            foreach ($arr as $key => $val) {
                if (isset($arr2[$val[$keyName]])) {
                    $arr2[$val[$keyName]][] = $val;
                } else {
                    $arr2[$val[$keyName]] = [$val];
                }
            }
        } else {
            foreach ($arr as $key => $val) {
                $arr2[$val[$keyName]] = $val;
            }
        }
        return $arr2;
    }

}

if (!function_exists('format_bytes')) {
    /**
     * 文件大小单位转换
     *
     * @param int $size 大小
     * @return string
     */
    function format_bytes(int $size): string
    {
        $units = array('B', 'K', 'M', 'G', 'T');
        $i = 0;
        for (; $size >= 1024 && $i < count($units); $i++) {
            $size /= 1024;
        }
        return round($size, 2) . $units[$i];
    }

}


if (!function_exists('get_rand_member')) {
    /**
     * 生成随机 UID
     * @param int $endNum
     * @return string
     */
    function get_rand_member($endNum = 0)
    {
        $endNum = ($endNum <= 0 ? rand(4, 10) : $endNum);
        $str = rand(11111111, 99999999);
        $length = strlen($str) - 1;
        $substr = substr($str, rand(0, $length), rand(0, $length));
        $str .= $substr;
        $endStr = $str . rand(111111, 999999);
        $str = '';
        for ($i = 0; $i < $endNum; $i++) {
            $str .= $endStr[mt_rand(0, strlen($endStr) - 1)];
        }
        $str = strtolower($str);
        if ($str <= 0) {
            get_rand_member($endNum);
        }
        return $str;
    }
}


if (!function_exists('handle_address')) {
    /**
     * 处理地址获取省市区信息
     *
     * @param string $address 地址
     * @return array|string[]
     */
    function handle_address($address)
    {
        preg_match('/(.*?(省|自治区|特别行政区|北京市|天津市|上海市|重庆市))/', $address, $matches);
        $province = '';
        if (count($matches) > 1) {
            $province = $matches[count($matches) - 2];
            $address = str_replace($province, '', $address);
        }
        if (in_array($province, ['北京市', '天津市', '上海市', '重庆市', '香港特别行政区', '澳门特别行政区'])) {
            $city = $province;
        } else {
            preg_match('/(.*?(市|自治州|地区|区划|县|特别行政区))/', $address, $matches);
            if (count($matches) > 1) {
                $city = $matches[count($matches) - 2];
                $address = str_replace($city, '', $address);
            }
        }
        preg_match('/(.*?(区|县|镇|乡|街道))/', $address, $matches);
        if (count($matches) > 1) {
            $area = $matches[count($matches) - 2];
            $address = str_replace($area, '', $address);
        }
        return [
            'province' => isset($province) ? $province : '',
            'city' => isset($city) ? $city : '',
            'area' => isset($area) ? $area : '',
        ];
    }
}
if (!function_exists('goods_attr_format')) {
    /**
     * 获取商品属性信息
     *
     * @param array $attr 商品属性
     * @return array
     */
    function goods_attr_format($attr)
    {
        $data = [];
        foreach ($attr[0]['detail'] as $k => $v) {
            $data[] = [
                $attr[0]['value'] => $v
            ];
        }
        foreach ($attr as $k => $v) {
            if ($k > 0) {
                $data = goods_attr_combine($data, $v);
            }
        }
        return $data;
    }

}
if (!function_exists('generate_pdf_file')) {
    /**
     * 生成pdf文件
     *
     * @param string|array $html html内容
     * @param string $fileName 文件名称 不设置直接输出pdf内容
     * @return mixed|string 文件地址
     * @throws \Mpdf\MpdfException
     */
    function generate_pdf_file($html, $fileName = '')
    {
        $dir = explode('/', $fileName);
        if (count($dir) > 1) {
            unset($dir[count($dir) - 1]);
            $dir = implode('/', $dir);
            if (!is_dir($dir)) {
                mkdir($dir, 0777, true);
            }
        }
        $mpdf = new \Mpdf\Mpdf(['tempDir' => app()->getRootPath() . 'runtime/pdf_tmp']);

        $mpdf->autoLangToFont = true;
        $mpdf->autoScriptToLang = true;

        if (is_array($html)) {
            foreach ($html as $k => $v) {
                $mpdf->AddPageByArray([
                    'margin-left' => 10,
                    'margin-right' => 10,
                    'margin-top' => 12,
                    'margin-bottom' => 12
                ]);
                $mpdf->WriteHTML($v);
            }
        } else {
            $mpdf->AddPageByArray([
                'margin-left' => 10,
                'margin-right' => 10,
                'margin-top' => 12,
                'margin-bottom' => 12
            ]);
            $mpdf->WriteHTML($html);
        }

        $mpdf->Output($fileName);

        return $fileName;
    }
}
if (!function_exists('uuid')) {
    /**
     * 生成uuid
     *
     * @return string
     */
    function uuid()
    {
        $chars = md5(uniqid(mt_rand(), true));
        $uuid = substr($chars, 0, 8) . '-'
            . substr($chars, 8, 4) . '-'
            . substr($chars, 12, 4) . '-'
            . substr($chars, 16, 4) . '-'
            . substr($chars, 20, 12);
        return $uuid;
    }
}

if (!function_exists('authcode')) {
    /**
     *
     * 非常给力的authcode加密函数,Discuz!经典代码(带详解)
     * 函数authcode($string, $operation, $key, $expiry)中的$string：字符串，明文或密文；$operation：DECODE表示解密，其它表示加密；$key：密匙；$expiry：密文有效期。
     * @return false|string
     */
    function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0)
    {
        // 动态密匙长度，相同的明文会生成不同密文就是依靠动态密匙
        $ckey_length = 4;

        // 密匙
        $key = md5($key ? $key : '');

        // 密匙a会参与加解密
        $keya = md5(substr($key, 0, 16));
        // 密匙b会用来做数据完整性验证
        $keyb = md5(substr($key, 16, 16));
        // 密匙c用于变化生成的密文
        $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';
        // 参与运算的密匙
        $cryptkey = $keya . md5($keya . $keyc);
        $key_length = strlen($cryptkey);
        // 明文，前10位用来保存时间戳，解密时验证数据有效性，10到26位用来保存$keyb(密匙b)，
        //解密时会通过这个密匙验证数据完整性
        // 如果是解码的话，会从第$ckey_length位开始，因为密文前$ckey_length位保存 动态密匙，以保证解密正确
        $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
        $string_length = strlen($string);
        $result = '';
        $box = range(0, 255);
        $rndkey = array();
        // 产生密匙簿
        for ($i = 0; $i <= 255; $i++) {
            $rndkey[$i] = ord($cryptkey[$i % $key_length]);
        }
        // 用固定的算法，打乱密匙簿，增加随机性，好像很复杂，实际上对并不会增加密文的强度
        for ($j = $i = 0; $i < 256; $i++) {
            $j = ($j + $box[$i] + $rndkey[$i]) % 256;
            $tmp = $box[$i];
            $box[$i] = $box[$j];
            $box[$j] = $tmp;
        }
        // 核心加解密部分
        for ($a = $j = $i = 0; $i < $string_length; $i++) {
            $a = ($a + 1) % 256;
            $j = ($j + $box[$a]) % 256;
            $tmp = $box[$a];
            $box[$a] = $box[$j];
            $box[$j] = $tmp;
            // 从密匙簿得出密匙进行异或，再转成字符
            $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
        }
        if ($operation == 'DECODE') {
            // 验证数据有效性，请看未加密明文的格式
            if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {
                return substr($result, 26);
            } else {
                return '';
            }
        } else {
            // 把动态密匙保存在密文里，这也是为什么同样的明文，生产不同密文后能解密的原因
            // 因为加密后的密文可能是一些特殊字符，复制过程可能会丢失，所以用base64编码
            return $keyc . str_replace('=', '', base64_encode($result));
        }
    }
}
if (!function_exists('formatCascaderData')) {
    function formatCascaderData(&$options, $name = '', $baseLevel = 0, $pidName = 'pid', $pid = 0, $level = 0, $data = []): array
    {
        if ($level === 0 && !is_array(current($options))) {
            $temp = [];
            foreach ($options as $k => $v) {
                $temp[] = [
                    'value' => $k,
                    'label' => $v
                ];
            }
            return $temp;
        }
        $_options = $options;
        foreach ($_options as $k => $option) {
            if ($option[$pidName] == $pid) {
                $value = ['value' => $k, 'label' => $option[$name]];
                unset($options[$k]);
                $value['children'] = formatCascaderData($options, $name, $baseLevel, $pidName, $k, $level + 1);
                if (!count($value['children'])) unset($value['children']);
                $data[] = $value;
            }
        }
        return $data;
    }
}
if (!function_exists('formatCascaderDataAsset')) {
    function formatCascaderDataAsset(&$options, $name = '', $baseLevel = 0, $pidName = 'pid', $pid = 0, $level = 0, $data = [], $picture = 'picture', $isShow = 'is_show'): array
    {
        if ($level === 0 && !is_array(current($options))) {
            $temp = [];
            foreach ($options as $k => $v) {
                $temp[] = [
                    'value' => $k,
                    'label' => $v
                ];
            }
            return $temp;
        }
        $_options = $options;
        foreach ($_options as $k => $option) {
            if ($option[$pidName] == $pid) {
                $value = ['value' => $k, 'label' => $option[$name], 'picture' => $option[$picture], 'is_show' => $option[$isShow]];
                unset($options[$k]);
                $value['children'] = formatCascaderDataAsset($options, $name, $baseLevel, $pidName, $k, $level + 1);
                if (!count($value['children'])) unset($value['children']);
                $data[] = $value;
            }
        }
        return $data;
    }
}
if (!function_exists('bubbleSort')) {
    /**
     * 冒泡排序 从小到大
     *
     * @param array $arr 数组
     * @param string|null $key 键名
     * @return array
     */
    function bubbleSort(array $arr, $key = null)
    {
        if ($key) {
            for ($i = 0; $i < count($arr); $i++) {
                //设置一个空变量
                $data = '';
                for ($j = $i; $j < count($arr) - 1; $j++) {
                    if ($arr[$i][$key] > $arr[$j + 1][$key]) {
                        $data = $arr[$i];
                        $arr[$i] = $arr[$j + 1];
                        $arr[$j + 1] = $data;
                    }
                }
            }
        } else {
            for ($i = 0; $i < count($arr); $i++) {
                //设置一个空变量
                $data = '';
                for ($j = $i; $j < count($arr) - 1; $j++) {
                    if ($arr[$i] > $arr[$j + 1]) {
                        $data = $arr[$i];
                        $arr[$i] = $arr[$j + 1];
                        $arr[$j + 1] = $data;
                    }
                }
            }
        }
        return $arr;
    }
}

if (!function_exists('get_property_code')) {
    /**
     * 根据传值 生成唯一的物业编码
     * @param $str
     * @return false|float|int
     */
    function get_property_code($num = 5)
    {
        $binary = '01UX2H9BS3DTFGUN4VK5LOPRW6AC7IJI8PQ6RJ9Y1Z';
        $name = substr(str_shuffle($binary), mt_rand(0, strlen($binary) - 11), $num);
        return $name;
    }
}

if (!function_exists('get_random')) {
    /**
     * 根据传值 生成唯一的随机编码
     * @param $str
     * @return false|float|int
     */
    function get_random($num = 5)
    {
        $binary = '01UX2H9BS3DTFGUN4VK5LOPRW6AC7IJI8PQ6RJ9Y1Z';
        $name = substr(str_shuffle($binary), mt_rand(0, strlen($binary) - 11), $num);
        return $name;
    }
}

if (!function_exists('formatCategory')) {
    function formatCategory(array $data, string $idName = "id", string $fieldName = 'pid', $childrenKey = 'children')
    {
        $items = [];
        foreach ($data as $item) {
            $items[$item[$idName]] = $item;
        }
        $result = array();
        foreach ($items as $item) {
            if (isset($items[$item[$fieldName]])) {
                $items[$item[$fieldName]][$childrenKey][] = &$items[$item[$idName]];
            } else if ($item[$fieldName] == 0) {
                $result[] = &$items[$item[$idName]];
            }
        }
        return $result;
    }
}